OpenGL Programming/Modern OpenGL Tutorial Load OBJ 您所在的位置:网站首页 ObjectLoader OpenGL Programming/Modern OpenGL Tutorial Load OBJ

OpenGL Programming/Modern OpenGL Tutorial Load OBJ

2024-06-17 07:26| 来源: 网络整理| 查看: 265

While you can create any shape by typing vertices by hand, it's much more practical to edit shapes from a dedicated editor. Unfortunately, openGL does not include any mesh reading functions. However, the .obj format is quite easy to parse, and most 3d programs, including blender, has export functionality for it. In this tutorial, we will focus on getting Suzan the monkey from blender into our openGL program.

Contents 1 Creating Suzanne 2 File format 3 Flat-shading - duplicating vertices and normals 3.1 Averaging normals 3.2 Pre-computed normals 4 See also Creating Suzanne[edit | edit source]

Wikipedia has related information at Blender (software)#Suzanne

See also the Wikibook Blender 3D: Noob to Pro.

Blender screenshot

Suzanne is the Blender test model. It has 500 polygons, which makes it a good test for us.

To create it, run Blender (we'll use version 2.58), then:

Remove all elements from the scene (right click on them and press x) In the top menu, click on Add > Mesh > Monkey Type n to display the Transform panel and set the location to (0, 0, 0) set the rotation to (90, 0, 0) In the top menu, click on File > Export > Wavefront (.obj) to preserve the Blender orientation, carefully set the following options (to switch to "Y-is-up" OpenGL coordinates): Forward: -Z Forward Up: Y Up Tick "Triangulate" so we get triangle faces instead of quad faces

Blender will create two files, suzanne.obj and suzanne.mtl:

the .obj file contains the mesh : vertices and faces the .mtl file contains information on materials (Material Template Library)

For now we'll just load the mesh.

File format[edit | edit source]

Wikipedia has related information at Wavefront .obj file

Inspect the .obj file with a text editor. We see that the format is pretty simple:

structured in lines lines starting with # are comments o introduces a new object v introduces a vertex vn introduces a normal f introduces a face, using vertex indices, starting at 1

We need to populate several C arrays:

the vertices the elements the normals (used for lighting computations)

The format also has other features, but for now we'll leave them aside.

Here's a first, crude implementation that will work for our object.

Our parser is going to be limited (no support for multiple objects, alternative vertex formats, polygons, etc.), but that's enough for our immediate needs.

void load_obj(const char* filename, vector &vertices, vector &normals, vector &elements) { ifstream in(filename, ios::in); if (!in) { cerr v.z; v.w = 1.0f; vertices.push_back(v); } else if (line.substr(0,2) == "f ") { istringstream s(line.substr(2)); GLushort a,b,c; s >> a; s >> b; s >> c; a--; b--; c--; elements.push_back(a); elements.push_back(b); elements.push_back(c); } /* anything else is ignored */ } normals.resize(vertices.size(), glm::vec3(0.0, 0.0, 0.0)); for (int i = 0; i vertices.size(), 0); for (int i = 0; i elements.size(); i+=3) { GLushort ia = mesh->elements[i]; GLushort ib = mesh->elements[i+1]; GLushort ic = mesh->elements[i+2]; glm::vec3 normal = glm::normalize(glm::cross( glm::vec3(mesh->vertices[ib]) - glm::vec3(mesh->vertices[ia]), glm::vec3(mesh->vertices[ic]) - glm::vec3(mesh->vertices[ia]))); int v[3]; v[0] = ia; v[1] = ib; v[2] = ic; for (int j = 0; j normals[cur_v] = normal; } else { // average mesh->normals[cur_v].x = mesh->normals[cur_v].x * (1.0 - 1.0/nb_seen[cur_v]) + normal.x * 1.0/nb_seen[cur_v]; mesh->normals[cur_v].y = mesh->normals[cur_v].y * (1.0 - 1.0/nb_seen[cur_v]) + normal.y * 1.0/nb_seen[cur_v]; mesh->normals[cur_v].z = mesh->normals[cur_v].z * (1.0 - 1.0/nb_seen[cur_v]) + normal.z * 1.0/nb_seen[cur_v]; mesh->normals[cur_v] = glm::normalize(mesh->normals[cur_v]); } } } Pre-computed normals[edit | edit source]

TODO: improve the parser to support .obj normals

The Obj format supports pre-computed normals. Interestingly they are specified in the faces, so if a vertex is present on several faces, it may get different normals, which means we have to use the vertex duplication technique discussed above.

For instance, a basic export of Suzanne references vertex #1 with two different normals #1 and #7:

v 0.437500 0.164063 0.765625 ... vn 0.664993 -0.200752 0.719363 ... f 47//1 1//1 3//1 ... f 1//7 11//7 9//7 f 1//7 9//7 3//7

By comparison, the MD2/MD3 format (used by Quake among others) also include pre-computed normals, but they are attached to vertices, not to faces.

See also[edit | edit source] TooL: The OpenGL OBJ Loader, released under the GNU GPL (but OpenGL 1.x) - Comment on this page

- Recent stats

< OpenGL Programming

Browse & download complete code


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有